package com.facebook.games.fa.model
{
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.TextFlow;
	
	import mx.collections.ArrayCollection;
	
	/**
	 * Carta
	 * @author Diego Maehler <dmaehler@gmail.com>
	 */
	[Bindable]
	public class Card
	{
		
		public var id : int;
		
		/**
		 * Atleta
		 */
		private var _athlete : Athlete;
		
		/**
		 * Clone do atleta atual para guardar os seus atributos iniciais
		 */ 
		private var athleteBeforeJoker : Athlete;
		
		/**
		 * Lista das Cartas coringa
		 */
		private var _jokerCards : ArrayCollection = new ArrayCollection();
		
		public function get athlete():Athlete
		{
			return _athlete;
		}
		
		public function set athlete(value:Athlete):void
		{
			_athlete = value;
			if (athlete != null) {
				_athlete.card = this;
				this.athleteWithoutJokerCards = athlete.clone();
			}
		}

		/**
		 * 
		 */
		public function Card (athlete : Athlete = null)
		{
			this.athlete = athlete;
		}
		
		public function get jokerCards():ArrayCollection
		{
			return _jokerCards;
		}

		/**
		 * @private
		 */
		protected function set jokerCards(value:ArrayCollection):void
		{
			_jokerCards = value;
		}
		
		public function get athleteWithoutJokerCards () : Athlete
		{
			return this.athleteBeforeJoker; 
		}
		
		protected function set athleteWithoutJokerCards (athlete : Athlete) : void
		{
			this.athleteBeforeJoker = athlete;
		}
		
		/**
		 * Adiciona uma carta coringa
		 * @param Carta Coringa
		 */
		public function addJokerCard (jokerCard : JokerCard) : void
		{
			
			if (!this.jokerCards.contains(jokerCard)) {
				
				this.jokerCards.addItem(jokerCard);
				
				if (this.athleteBeforeJoker == null) {
					this.athleteWithoutJokerCards = this.athlete.clone();
				}
				
				if (!this.isAttributeAnnuled(jokerCard.attribute.name)) {
					switch (jokerCard.type) {
						case JokerCard.INCREASE : this.athlete.increaseAttributeValue(jokerCard.attribute.name, jokerCard.attribute.value); break;
						case JokerCard.DECREASE : this.athlete.decreaseAttributeValue(jokerCard.attribute.name, jokerCard.attribute.value); break;
						case JokerCard.CANCEL	: this.athlete.cancelAttribute(jokerCard.attribute.name); break;
					}
				}
				
			}
			
		}
		
		/**
		 * Remove uma Carta coringa que tenha sido adicionada
		 * @param jokerCard
		 */
		public function removeJokerCard (jokerCard : JokerCard) : void
		{
			if (this.jokerCards.contains(jokerCard)) {
				
				this.jokerCards.removeItemAt(this.jokerCards.getItemIndex(jokerCard));
				
				switch (jokerCard.type) {
					case JokerCard.INCREASE : this.athlete.decreaseAttributeValue(jokerCard.attribute.name, jokerCard.attribute.value); break;
					case JokerCard.DECREASE : this.athlete.increaseAttributeValue(jokerCard.attribute.name, jokerCard.attribute.value); break;
					case JokerCard.CANCEL	: this.athlete.increaseAttributeValue(jokerCard.attribute.name, this.athleteBeforeJoker.getAttributeValue(jokerCard.attribute.name)); break;
				}
				
			}
		}
		
		/**
		 * Compara um atributo deste atleta com o atributo do atleta de outra carta
		 * @param card
		 * @param attributeName
		 * @return
		 * 		-1 - O valor do atributo do outro atleta é maior que o valor deste 
		 * 		0 - Os valores são iguais
		 * 		1 - O valor do atributo deste atleta é maior que o do outro atleta
		 */
		public function compareAthletesAttribute (card : Card, attributeName : String) : int
		{
			return this.athlete.compareAttribute(card.athlete, attributeName);
		}
		
		/**
		 * Retorna se esta carta foi acrescida de Cartas coringa
		 * @return TRUE | FALSE
		 */
		public function haveJokerCards () : Boolean
		{
			return this.jokerCards.length > 0;
		}
		
		/**
		 * Retorna a string dos valores do atributos, ex: 120 + 10 + 38, 
		 * isto significa que o atributo inicial do atleta era 120, 
		 * depois foram acrescidas duas cartas coringas.
		 * @param attributeName
		 * @return
		 */ 
		public function attributeToString (attributeName : String) : TextFlow
		{
			
			const tf : TextFlow = new TextFlow();
			
			if (this.isAttributeAnnuled(attributeName)) {
				tf.addChild(this.getSpanElement("0", 0x0000ff, true));
			} else {
	
				if (this.haveJokerCards()) {
					
					tf.addChild(this.getSpanElement(this.athleteWithoutJokerCards.getAttributeValue(attributeName).toString(), 0x000000, false));
						
					for each (var jokerCard : JokerCard in this._jokerCards) {
						if (jokerCard.attribute.name == attributeName) {
							switch (jokerCard.type) {
								case JokerCard.INCREASE : tf.addChild(this.getSpanElement(" + " + jokerCard.attribute.value, 0xff0000, false)); break;
								case JokerCard.DECREASE : tf.addChild(this.getSpanElement(" - " + jokerCard.attribute.value, 0x0000ff, false)); break;
							}
						}
					}
					tf.addChild(this.getSpanElement(" = " + this.athlete.getAttributeValue(attributeName), 0x000000, true));
				} else {
					tf.addChild(this.getSpanElement(this.athlete.getAttributeValue(attributeName), 0x000000, true));
				}
			
			}
			
			return tf;
			
		}
		
		/**
		 * Monta um spanElement com o texto e a cor informados.
		 * @param texto
		 * @param cor
		 * @return spanElement
		 */
		private function getSpanElement (text : String, color : uint, bold : Boolean) : SpanElement
		{
			const span : SpanElement = new SpanElement();
			span.text = text;
			span.color = color;
			span.fontWeight = bold ? "bold" : "normal";
			return span;
		}
		
		/**
		 * Verifica se o atributo da carta não foi anulado por uma carta coringa
		 * @param attributeName
		 * @return TRUE | FALSE
		 */
		public function isAttributeAnnuled (attributeName : String) : Boolean
		{
			for each (var joker : JokerCard in this._jokerCards) {
				if (joker.attribute.name == attributeName && joker.type == JokerCard.CANCEL) {
					return true;
				}
			}
			return false;
		}
		
	}
}